"use strict";

var  radon = require('radon')
	,util = radon.util
	,http = require('http')
	,https = require('https')
	,url = require('url');

var agentConfig = {
	keepAlive: true,
	maxFreeSockets: 50
};
// new一个keepalive的http的agent
var httpAgent = new http.Agent(agentConfig);
// new一个keepalive的https的agent
var httpsAgent = new https.Agent(agentConfig);

function throwError(code, message){
	var err = new Error(message);
	err.code = code;
	throw err;
}

var TokenExpire = 5 * 60 * 1000;

//param {config} 自身产品的配置信息,包括产品id, 产品token, UC api url
function UCClient(config, callbacks, context){
	// 创建事件触发器
	var self = this;
	self.$callbacks = callbacks;
	self.$context = context || self;
	self.setConfig(config);
}
UCClient.prototype = {
	setConfig: function(config)
	{
		var self = this;
		self.$events = [];
		self.id = config.id;
		self.token = config.token;
		if (config.remote)
		{
			self.remote = config.remote;
		}
		else if (config.url)
		{
			self.remote = url.parse(config.url);
		}

		if (!self.id || !self.token || !self.remote)
		{
			throwError(11106, 'UserCenter客户端没有正确配置');
		}
	},
	emit: util.generator(function*(evt){
		// 检查数据是否正确
		if (evt && evt.ts && evt.token && evt.data){
			var self = this;
			if (evt = self._checkToken(evt)){
				var cb = self.$callbacks[evt.action];
				// 验证是否有指定的操作可以调用
				if (typeof(cb) != 'function') {
					throwError(11101, '没有指定的UC客户端回调操作');
				}
				// 调用回调操作事件
				var args = Array.prototype.slice.call(arguments);
				args[0]  = evt.param || {};
				return yield cb.apply(self.$context, args);
			}else {
				throwError(11104, '验证错误,没有权限');
			}
		}else {
			throwError(11102, '产品参数错误');
		}
	}),
	_checkToken: function(evt){
		var self = this;
		var now = Date.now();
		var ts  = evt.ts;
		if (ts < 1e12)
		{
			ts *= 1000;
		}
		if (Math.abs(now - ts) <= TokenExpire)
		{
			if (evt.token == util.md5(self.token + evt.data + ts))
			{
				try {
					return JSON.parse(evt.data);
				}catch(err){
					throwError(11105, 'Data参数JSON格式错误');
				}
			}
		}
		return false;
	},

	/**
	 * 发送请求到用户中心服务器接口
	 * @action {Object} action 请求的操作类型
	 * @param  {Object} param  请求参数对象
	 * @return {Object}        返回服务器响应结果
	 */
	send: util.generator(function *(action, param)
	{
		var self = this;
		var time = Date.now();
		var postData = JSON.stringify({
			'id': self.id,
			'action': action,
			'param': param
		});
		var remote  = self.remote;
		var enToken = util.md5(self.token + postData + time);
		var data 	= 'data=' + encodeURIComponent(postData);
		var options = {
			'hostname': remote.hostname,
			'host': remote.host,
			'port': remote.port,
			'path': remote.path +
				'?token=' + enToken +
				'&ts=' + time +
				'&id=' + self.id,
			'headers': {
				'Content-Type': 'application/x-www-form-urlencoded',
				'Content-Length': data.length,
				'Accept': 'application/json'
			},
			'method': 'POST',
			'agent': (remote.protocol == 'http:') ? httpAgent : httpsAgent
		};

		var result = [];
		try {
			yield util.promise(
				function(done, fail)
				{
					let mod = (remote.protocol == 'http:') ? http : https;
					var req = mod.request(options, function(res) {
						res.on('data', function(body) {
							result.push(body);
						});
						res.on('end', done);
					});
					req.once('error', fail).end(data);
				}
			);
		}
		catch (e)
		{
			throwError(509, '远程计算机拒绝连接');
		}

		// if no server responce, return null
		if (!result.length)
		{
			return null;
		}

		// parse the response data to the json object
		try {
			result = Buffer.concat(result).toString();
			result = JSON.parse(result);
			util.log(101, `Request CAS ${action} cost ${Date.now()-time} ms: ${options.path}`);
			return result;
		}
		catch (e)
		{
			util.log(100, 'UC API返回数据无效:\n%s', result);
			throwError(510, '远程计算机返回数据无效');
		}
	}),
	/**
	 * 验证授权ticket是否正确, 返回登陆信息
	 * @param  {String} ticket 授权码
	 * @return {Object}        返回用户中心授权检查结果
	 */
	verifyTicket: function(ticket){
		return this.send('verifyTicket', {'ticket': ticket});
	},
	//data: {userId}
	logoutCas: function(data){
		return this.send('logoutCas', data);
	},
	//data: {loginId,switchId};
	switchUser: function(data){
		return this.send('switchUser', data);
	},
	// 创建产品账号通知UC
	createAccount: function(data){
		return this.send('createAccount', data);
	},
	/**
	 * 获取用户某产品下的可切换产品账号列表
	 * @param data: {userId: }
	 * @returns {accounts: [{id: name: email:}]}
	 */
	switchList: function(data){
		return this.send('switchList', data);
	},
	/**
	 * 获取用户权限信息
	 * @param data: {keys: [{uid: aid:}]}
	 * @returns [{uid: aid: rights:}]
	 */
	getUserRights: function(data){
		return this.send('getUserRights', data);
	},
	/**
	 * 获取用户的可选角色
	 * @param data: {userId: }
	 * @returns {roles: [{id: name:}]}
	 */
	roleOption: function(data){
		return this.send('roleOption', data);
	},
	/**
	 * 获取客户的可选客户
	 * @param data: {all: boolean} 全部包括已删除，todo 开关all将来应该关闭, 暂时用于DSP同步账号数据用
	 * @param data: {userId: }
	 * @returns [{id: name: email:}]
	 */
	primaryOption: function(data){
		return this.send('primaryOption', data);
	},
	/**
	 * 获取客户的可选员工
	 * @param data: {userId: }
	 * @returns [{id: name: email:}]
	 */
	employeeOption: function(data){
		return this.send('employeeOption', data);
	}
};

module.exports = UCClient;